/**
 * 防止按钮多次点击（防抖函数）,采用settimeout延迟清除计时器
 * @param {*} fn
 * @param {*} time
 * @param {*} context
 * @returns
 */
const avoidClick = function (fn, time, context = this) {
  if (typeof fn !== "function") {
    throw new Error("Expected a function as the first argument.");
  }

  let id = null;

  const safeCall = function () {
    if (id) {
      return;
    }
    try {
      fn.apply(context);
      id = setTimeout(() => {
        cancel(); // 到时间了要清除之前的定时器
      }, time);
    } catch (error) {
      console.error(error);
      // 可以在这里添加更多的错误处理逻辑
    }
  };

  const cancel = function () {
    clearTimeout(id);
    id = null;
  };

  return {
    call: safeCall,
    cancel,
  };
};


/**
 * 节流函数，防止频繁触发，在限定的之间内只执行一次
 * 通过时间间差来判断是否需要执行
 * @param {*} callback 
 * @param {*} timeout 
 * @returns 
 */
const throttle=function(callback, timeout){
  let pre = 0;
  return function () {
    // 计算时间差（当前时间-上次执行的时间），小于时间范围，不执行
    const now = Date.now();
    if (now - pre > timeout) {
      pre = now;
      callback.call();
    }
  };
}
/**
 * 一个记忆化函数，该函数使用闭包来存储已经计算过的值，以便在后续调用时能够快速返回结果，而不是重新计算。
 * @param {*} fn
 * @returns
 */
const memorize = (fn) => {
  const cache = {};
  return function (...args) {
    const key = JSON.stringify(args);
    let result = null;
    if (key in cache) {
      result = cache[key];
    } else {
      result = fn.apply(this, args);
      cache[key] = result;
    }
    return result;
  };
};



